import { Tile } from "./tile";

/*
  网格类，用于管理游戏中的格子
*/
export class Grid {
  maxRow: number; //最大行数
  boxRow: number; //box容纳的最大行数
  maxCol: number;//最大列数
  allColorSet: string[];//当前5种颜色集合
  availableColorSet: any[] = [];//可用颜色集合
  cells: any[][] = [[]]; //二维数组
  constructor(map: any, colorset: string[], maxRow: number, maxCol: number, boxRow: number) {
    this.maxRow = maxRow;
    this.maxCol = maxCol;
    this.boxRow = boxRow;
    this.allColorSet = colorset;
    this.cells = this.fromState(map);
  }

  getRowSize(x: number) {
    const isEven = x % 2 === 0; //偶数行
    const rowSize = isEven ? this.maxCol : this.maxCol - 1
    return rowSize;
  }

  fromState(map: any[][]) {
    const cells = [];
    for (let x = 0; x < this.boxRow; x++) {
      const row: any = cells[x] = [];
      for (let y = 0; y < this.getRowSize(x); y++) {
        if (typeof map?.[x]?.[y] === 'number') {
          const colorIndex = map[x][y];
          const color = this.allColorSet[colorIndex]
          row.push(new Tile({ x, y }, color));
        } else {
          row.push(null);
        }
      }
    }
    return cells;
  }

  getRandomColor() {
    return this.availableColorSet[Math.floor(Math.random() * this.availableColorSet.length)]
  }

  updateGrid(map: any[], tile: Tile, boxRow: number) {
    this.boxRow = boxRow;
    const newMap = [...map]
    if (newMap[tile.x]) {
      newMap[tile.x][tile.y] = this.allColorSet.indexOf(tile.color)
    } else {
      const newRow: any = newMap[tile.x] = [];
      for (let y = 0; y < this.getRowSize(tile.x); y++) {
        if (y == tile.y) {
          newRow.push(this.allColorSet.indexOf(tile.color));
        } else {
          newRow.push(null);
        }
      }
    }
    // console.log('updateGrid前', map, this.cells);
    this.cells = this.fromState(newMap);
    // console.log('updateGrid后', newMap, this.cells);
  }

  // 返回所有可用单元格
  availableCells() {
    const cells: any[] = [];

    this.eachCell((x: any, y: any, tile: any) => {
      if (!tile) {
        // 返回没有被占用的砖块坐标
        cells.push({ x, y });
      }
    });

    return cells;
  }

  //  返回占用的单元格
  occupiedCells() {
    const cells: any[] = [];

    this.eachCell((x: any, y: any, tile: any) => {
      if (tile) {
        // 返回没有被占用的砖块坐标
        cells.push({ x, y });
      }
    });

    return cells;
  }

  // 遍历获取size边界内所有单元格
  eachCell(callback: { (x: any, y: any, tile: any): void; (arg0: number, arg1: number, arg2: never): void; }) {
    for (let x = 0; x < this.boxRow; x++) {
      for (let y = 0; y < this.getRowSize(x); y++) {
        callback(x, y, this.cells[x][y]);
      }
    }
  }

  // 检查是否还有可用单元格
  cellsAvailable() {
    return !!this.availableCells().length; //!!1	true	!!0	false
  }

  // 获取单元格内容
  cellContent(cell: { x: number; y: number; }) {
    if (this.withinBounds(cell)) {
      return this.cells[cell.x][cell.y];
    } else {
      return null;
    }
  }
  removeTile(tile: { x: number; y: number; }) {
    this.cells[tile.x][tile.y] = null;
  }

  withinBounds(position: { x: any; y: any; }) {
    return position.x >= 0 && position.x < this.boxRow &&
      position.y >= 0 && position.y < this.getRowSize(position.x);
  }
  // 返回最大且有内容的行
  lastCellContent() {
    // 倒序遍历行
    for (let x = this.boxRow - 1; x >= 0; x--) {
      const row = this.cells[x];
      if (!row) continue;

      // 正序遍历列，找到第一个非空项即可
      for (let y = 0; y < this.getRowSize(x); y++) {
        if (row[y]) {
          return { x, y };
        }
      }
    }

    return null;
  }
  serialize() {
    const cellState = [];
    const map: any = [];
    const userdColorSet: any = [];
    for (let x = 0; x < this.boxRow; x++) {
      const row: any = cellState[x] = [];
      map[x] = [];
      for (let y = 0; y < this.getRowSize(x); y++) {
        const tile: any = this.cells[x][y];
        if (tile) userdColorSet.push(tile.color)
        row.push(tile ? tile : null);
        map[x][y] = tile ? this.allColorSet.indexOf(tile.color) : null
      }
      this.availableColorSet = [...new Set(userdColorSet)];
    }
    return {
      cells: cellState,
      map
    };
  }
}